package com.ulife.permission.common;

import static com.alibaba.citrus.turbine.util.TurbineUtil.getTurbineRunData;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.alibaba.citrus.service.pipeline.PipelineContext;
import com.alibaba.citrus.service.pipeline.support.AbstractValve;
import com.alibaba.citrus.turbine.support.TurbineRunDataImpl;
import com.ulife.common.Result;
import com.ulife.common.WebConstant;
import com.ulife.common.exception.ManagerException;
import com.ulife.permission.dao.dataobject.RoleDO;
import com.ulife.permission.dao.dataobject.TargetDO;
import com.ulife.permission.dao.dataobject.UserDO;
import com.ulife.permission.manager.RoleManager;
import com.ulife.permission.manager.TargetManager;
import com.ulife.permission.manager.UserManager;
import com.ulife.permission.module.screen.RoleList;

public class PagePermissionValve extends AbstractValve {
	private static final Logger log = LoggerFactory.getLogger(RoleList.class);
	
	@Autowired
	private HttpServletRequest request;
	@Autowired
	private UserManager userManager;
	@Autowired
	private TargetManager targetManager;
	@Autowired
	private RoleManager roleManager;
	
	public void invoke(PipelineContext pipelineContext) throws Exception {
		TurbineRunDataImpl rundata = (TurbineRunDataImpl)getTurbineRunData(request);
		try {
			SysUser sysUser = (SysUser) request.getSession().getAttribute(WebConstant.SYS_USER_SESSION_KEY);
			List<String> userList = new ArrayList<String>();
			String userRoleStr = null;
			if (sysUser != null) {
				rundata.getContext().put("sysUser", sysUser);
				long id = sysUser.getId();
				Result<UserDO> userResult = userManager.getUserById(id);
				if (userResult != null && userResult.isSuccess() && null != userResult.getModule()) {
					UserDO user = userResult.getModule();
					userRoleStr = user.getRoleIdList();
				}
				if (StringUtils.equals(userRoleStr, "admin")) {
					putAllPermission(rundata);
				}else {
					if (userRoleStr != null) {
						String[] userRoles = StringUtils.split(userRoleStr, ",");
						CollectionUtils.addAll(userList, userRoles);
					}
					
					if (CollectionUtils.isNotEmpty(userList)) {
						dealPermission(userList, rundata);
					}
				}
			}
			String targetStr = rundata.getTarget();
			if (!PagePermissionConstants.isDontNeedAccess(targetStr) && !StringUtils.equals(userRoleStr, "admin")) {
				Result<TargetDO> targetResult = targetManager.getTargetByTargetId(PageEnum.getPageId(targetStr));
				if (sysUser != null) {
					boolean hasPermission = false;
					String allowRoleStr = null;
					
					if (targetResult != null && targetResult.isSuccess() && targetResult.getModule() != null) {
						TargetDO target = targetResult.getModule();
						allowRoleStr = target.getRoleList();
					}
					
					if (allowRoleStr != null) {
						String[] allowRoles = StringUtils.split(allowRoleStr, ",");
						List<String> allowList = new ArrayList<String>();
						CollectionUtils.addAll(allowList, allowRoles);	
						for (String allow : allowList) {
							if (userList.contains(allow)) {
								hasPermission = true;
							}
						}
					}
					
					if (!hasPermission) {
						rundata.redirectTo("noPermission");
					}
				}
				else {
					rundata.redirectTo("login");
				}
			}
		}catch (Exception e) {
			log.error("PagePermissionValve error", e);
			rundata.redirectTo("errorUrl");
		}
		pipelineContext.invokeNext();
	}

	private void putAllPermission(TurbineRunDataImpl rundata) {
		for(TargetEnum p : TargetEnum.values()) {
			rundata.getContext().put(p.getTarget(), p.getTarget());
		}
	}

	private void dealPermission(List<String> userList, TurbineRunDataImpl rundata) {
		if (CollectionUtils.isNotEmpty(userList)) {
			for (String rIdStr : userList) {
				long rId = Long.parseLong(rIdStr);
				try {
					Result<RoleDO> roleResult = roleManager.getRoleById(rId);
					if (roleResult != null && roleResult.isSuccess() && roleResult.getModule() != null) {
						RoleDO role = roleResult.getModule();
						String targetListStr = role.getTargetList();
						String functionListStr = role.getFunctionList();
						String[] targets = StringUtils.split(targetListStr, ",");
						String[] functions = StringUtils.split(functionListStr, ",");
						if (targets != null) {
							for (String t : targets) {
								rundata.getContext().put(t, t);
							}
						}
						if (functions != null) {
							for (String f : functions) {
								rundata.getContext().put(f, f);
							}
						}
					}
				} catch (ManagerException e) {
					log.error("get role by role id error, role id = " + rId, e);
				}
			}
		}
	}

}
